From 420e4ee2f7de785b6f6a661d08e590e0b4b2a773 Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Mon, 15 Jan 2001 19:48:53 +0000 Subject: [PATCH] New implementaion that more closely mimics the events that an X server 2001-01-15 Tor Lillqvist * gdk/win32/gdkevents-win32.c (synthesize_crossing_events): New implementaion that more closely mimics the events that an X server would generate. Especially, properly generate GDK_NOTIFY_VIRTUAL and GDK_NOTIFY_NONLINEAR_VIRTUAL crossing events. This makes buttons with nested preview widgets, for instance, more responsive when you move the mouse quickly into them. (find_window_for_pointer_event): Make it actually compile. (gdk_event_translate): Set send_event to the value of InSendMessage (). This doesn't really mean the same as X11's send_event flag, but is close enough, says jpe@archaeopteryx.com --- ChangeLog | 13 +++ ChangeLog.pre-2-0 | 13 +++ ChangeLog.pre-2-10 | 13 +++ ChangeLog.pre-2-2 | 13 +++ ChangeLog.pre-2-4 | 13 +++ ChangeLog.pre-2-6 | 13 +++ ChangeLog.pre-2-8 | 13 +++ gdk/win32/gdkevents-win32.c | 225 ++++++++++++++++++++++++++++++++++-- 8 files changed, 308 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index eedee06570..bed16ea3ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2001-01-15 Tor Lillqvist + + * gdk/win32/gdkevents-win32.c (synthesize_crossing_events): New + implementaion that more closely mimics the events that an X server + would generate. Especially, properly generate GDK_NOTIFY_VIRTUAL and + GDK_NOTIFY_NONLINEAR_VIRTUAL crossing events. This makes buttons + with nested preview widgets, for instance, more responsive when + you move the mouse quickly into them. + (find_window_for_pointer_event): Make it actually compile. + (gdk_event_translate): Set send_event to the value of + InSendMessage (). This doesn't really mean the same as X11's + send_event flag, but is close enough, says jpe@archaeopteryx.com + 2001-01-15 Alexander Larsson * gdk/linux-fb/gdkdnd-fb.c: diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index eedee06570..bed16ea3ff 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,16 @@ +2001-01-15 Tor Lillqvist + + * gdk/win32/gdkevents-win32.c (synthesize_crossing_events): New + implementaion that more closely mimics the events that an X server + would generate. Especially, properly generate GDK_NOTIFY_VIRTUAL and + GDK_NOTIFY_NONLINEAR_VIRTUAL crossing events. This makes buttons + with nested preview widgets, for instance, more responsive when + you move the mouse quickly into them. + (find_window_for_pointer_event): Make it actually compile. + (gdk_event_translate): Set send_event to the value of + InSendMessage (). This doesn't really mean the same as X11's + send_event flag, but is close enough, says jpe@archaeopteryx.com + 2001-01-15 Alexander Larsson * gdk/linux-fb/gdkdnd-fb.c: diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index eedee06570..bed16ea3ff 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,16 @@ +2001-01-15 Tor Lillqvist + + * gdk/win32/gdkevents-win32.c (synthesize_crossing_events): New + implementaion that more closely mimics the events that an X server + would generate. Especially, properly generate GDK_NOTIFY_VIRTUAL and + GDK_NOTIFY_NONLINEAR_VIRTUAL crossing events. This makes buttons + with nested preview widgets, for instance, more responsive when + you move the mouse quickly into them. + (find_window_for_pointer_event): Make it actually compile. + (gdk_event_translate): Set send_event to the value of + InSendMessage (). This doesn't really mean the same as X11's + send_event flag, but is close enough, says jpe@archaeopteryx.com + 2001-01-15 Alexander Larsson * gdk/linux-fb/gdkdnd-fb.c: diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index eedee06570..bed16ea3ff 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,16 @@ +2001-01-15 Tor Lillqvist + + * gdk/win32/gdkevents-win32.c (synthesize_crossing_events): New + implementaion that more closely mimics the events that an X server + would generate. Especially, properly generate GDK_NOTIFY_VIRTUAL and + GDK_NOTIFY_NONLINEAR_VIRTUAL crossing events. This makes buttons + with nested preview widgets, for instance, more responsive when + you move the mouse quickly into them. + (find_window_for_pointer_event): Make it actually compile. + (gdk_event_translate): Set send_event to the value of + InSendMessage (). This doesn't really mean the same as X11's + send_event flag, but is close enough, says jpe@archaeopteryx.com + 2001-01-15 Alexander Larsson * gdk/linux-fb/gdkdnd-fb.c: diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index eedee06570..bed16ea3ff 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,16 @@ +2001-01-15 Tor Lillqvist + + * gdk/win32/gdkevents-win32.c (synthesize_crossing_events): New + implementaion that more closely mimics the events that an X server + would generate. Especially, properly generate GDK_NOTIFY_VIRTUAL and + GDK_NOTIFY_NONLINEAR_VIRTUAL crossing events. This makes buttons + with nested preview widgets, for instance, more responsive when + you move the mouse quickly into them. + (find_window_for_pointer_event): Make it actually compile. + (gdk_event_translate): Set send_event to the value of + InSendMessage (). This doesn't really mean the same as X11's + send_event flag, but is close enough, says jpe@archaeopteryx.com + 2001-01-15 Alexander Larsson * gdk/linux-fb/gdkdnd-fb.c: diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index eedee06570..bed16ea3ff 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,16 @@ +2001-01-15 Tor Lillqvist + + * gdk/win32/gdkevents-win32.c (synthesize_crossing_events): New + implementaion that more closely mimics the events that an X server + would generate. Especially, properly generate GDK_NOTIFY_VIRTUAL and + GDK_NOTIFY_NONLINEAR_VIRTUAL crossing events. This makes buttons + with nested preview widgets, for instance, more responsive when + you move the mouse quickly into them. + (find_window_for_pointer_event): Make it actually compile. + (gdk_event_translate): Set send_event to the value of + InSendMessage (). This doesn't really mean the same as X11's + send_event flag, but is close enough, says jpe@archaeopteryx.com + 2001-01-15 Alexander Larsson * gdk/linux-fb/gdkdnd-fb.c: diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index eedee06570..bed16ea3ff 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,16 @@ +2001-01-15 Tor Lillqvist + + * gdk/win32/gdkevents-win32.c (synthesize_crossing_events): New + implementaion that more closely mimics the events that an X server + would generate. Especially, properly generate GDK_NOTIFY_VIRTUAL and + GDK_NOTIFY_NONLINEAR_VIRTUAL crossing events. This makes buttons + with nested preview widgets, for instance, more responsive when + you move the mouse quickly into them. + (find_window_for_pointer_event): Make it actually compile. + (gdk_event_translate): Set send_event to the value of + InSendMessage (). This doesn't really mean the same as X11's + send_event flag, but is close enough, says jpe@archaeopteryx.com + 2001-01-15 Alexander Larsson * gdk/linux-fb/gdkdnd-fb.c: diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index 51bed8a097..60995d4101 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -605,7 +605,7 @@ gdk_pointer_ungrab (guint32 time) static GdkWindow* find_window_for_pointer_event (GdkWindow* reported_window, - MSG* xevent) + MSG* msg) { HWND hwnd; POINTS points; @@ -615,26 +615,26 @@ find_window_for_pointer_event (GdkWindow* reported_window, if (p_grab_window == NULL || !p_grab_owner_events) return reported_window; - points = MAKEPOINTS(xevent->lParam); + points = MAKEPOINTS (msg->lParam); pt.x = points.x; pt.y = points.y; - ClientToScreen (xevent->hwnd, &pt); + ClientToScreen (msg->hwnd, &pt); GDK_NOTE (EVENTS, g_print ("Finding window for grabbed pointer event at (%ld, %ld)\n", pt.x, pt.y)); - hwnd = WindowFromPoint(pt); + hwnd = WindowFromPoint (pt); if (hwnd == NULL) return reported_window; - other_window = gdk_window_lookup(hwnd); + other_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); if (other_window == NULL) return reported_window; GDK_NOTE (EVENTS, g_print ("Found window %#x for point (%ld, %ld)\n", (guint) hwnd, pt.x, pt.y)); - gdk_window_unref(reported_window); - gdk_window_ref(other_window); + gdk_window_unref (reported_window); + gdk_window_ref (other_window); return other_window; } @@ -1122,6 +1122,10 @@ print_event (GdkEvent *event) g_print ("\n"); } +#if 0 + +/* Old implementation */ + static void synthesize_crossing_events (GdkWindow *window, MSG *msg) @@ -1216,6 +1220,207 @@ synthesize_crossing_events (GdkWindow *window, #endif } +#else + +/* New, improved implementation. */ + +static gboolean +gdk_window_is_child (GdkWindow *parent, + GdkWindow *window) +{ + if (parent == NULL || window == NULL) + return FALSE; + + return (gdk_window_get_parent (window) == parent || + gdk_window_is_child (parent, gdk_window_get_parent (window))); +} + +static void +synthesize_enter_or_leave_event (GdkWindow *window, + MSG *msg, + GdkEventType type, + GdkNotifyType detail, + gint x, + gint y) +{ + GdkEvent *event; + + event = gdk_event_new (); + event->crossing.type = type; + event->crossing.window = window; + event->crossing.send_event = FALSE; + gdk_window_ref (event->crossing.window); + event->crossing.subwindow = NULL; + event->crossing.time = msg->time; + event->crossing.x = x; + event->crossing.y = y; + event->crossing.x_root = msg->pt.x; + event->crossing.y_root = msg->pt.y; + event->crossing.mode = GDK_CROSSING_NORMAL; + event->crossing.detail = detail; + event->crossing.focus = TRUE; /* ??? */ + event->crossing.state = 0; /* ??? */ + + gdk_event_queue_append (event); + + if (type == GDK_ENTER_NOTIFY + && GDK_WINDOW_OBJECT (window)->extension_events != 0) + _gdk_input_enter_event (&event->crossing, window); + + GDK_NOTE (EVENTS, print_event (event)); +} + +static void +synthesize_leave_event (GdkWindow *window, + MSG *msg, + GdkNotifyType detail) +{ + POINT pt; + + if (!(GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->event_mask & GDK_LEAVE_NOTIFY_MASK)) + return; + + /* Leave events are at (current_x,current_y) in current_window */ + + if (current_window != window) + { + pt.x = current_x; + pt.y = current_y; + ClientToScreen (GDK_WINDOW_HWND (current_window), &pt); + ScreenToClient (GDK_WINDOW_HWND (window), &pt); + synthesize_enter_or_leave_event (window, msg, GDK_LEAVE_NOTIFY, detail, pt.x, pt.y); + } + else + synthesize_enter_or_leave_event (window, msg, GDK_LEAVE_NOTIFY, detail, current_x, current_y); + +} + +static void +synthesize_enter_event (GdkWindow *window, + MSG *msg, + GdkNotifyType detail) +{ + POINT pt; + + if (!(GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->event_mask & GDK_ENTER_NOTIFY_MASK)) + return; + + /* Enter events are at LOWORD (msg->lParam), HIWORD + * (msg->lParam) in msg->hwnd */ + + pt.x = LOWORD (msg->lParam); + pt.y = HIWORD (msg->lParam); + if (msg->hwnd != GDK_WINDOW_HWND (window)) + { + ClientToScreen (msg->hwnd, &pt); + ScreenToClient (GDK_WINDOW_HWND (window), &pt); + } + synthesize_enter_or_leave_event (window, msg, GDK_ENTER_NOTIFY, detail, pt.x, pt.y); +} + +static void +synthesize_enter_events (GdkWindow *from, + GdkWindow *to, + MSG *msg, + GdkNotifyType detail) +{ + GdkWindow *prev = gdk_window_get_parent (to); + + if (prev != from) + synthesize_enter_events (from, prev, msg, detail); + synthesize_enter_event (to, msg, detail); +} + +static void +synthesize_leave_events (GdkWindow *from, + GdkWindow *to, + MSG *msg, + GdkNotifyType detail) +{ + GdkWindow *next = gdk_window_get_parent (from); + + synthesize_leave_event (from, msg, detail); + if (next != to) + synthesize_leave_events (next, to, msg, detail); +} + +static void +synthesize_crossing_events (GdkWindow *window, + MSG *msg) +{ + GdkWindow *intermediate, *tem, *common_ancestor; + + if (gdk_window_is_child (current_window, window)) + { + /* Pointer has moved to an inferior window. */ + synthesize_leave_event (current_window, msg, GDK_NOTIFY_INFERIOR); + + /* If there are intermediate windows, generate ENTER_NOTIFY + * events for them + */ + intermediate = gdk_window_get_parent (window); + if (intermediate != current_window) + { + synthesize_enter_events (current_window, intermediate, msg, GDK_NOTIFY_VIRTUAL); + } + + synthesize_enter_event (window, msg, GDK_NOTIFY_ANCESTOR); + } + else if (gdk_window_is_child (window, current_window)) + { + /* Pointer has moved to an ancestor window. */ + synthesize_leave_event (current_window, msg, GDK_NOTIFY_ANCESTOR); + + /* If there are intermediate windows, generate LEAVE_NOTIFY + * events for them + */ + intermediate = gdk_window_get_parent (current_window); + if (intermediate != window) + { + synthesize_leave_events (intermediate, window, msg, GDK_NOTIFY_VIRTUAL); + } + } + else if (current_window) + { + /* Find least common ancestor of current_window and window */ + tem = current_window; + do { + common_ancestor = gdk_window_get_parent (tem); + tem = common_ancestor; + } while (common_ancestor && + !gdk_window_is_child (common_ancestor, window)); + if (common_ancestor) + { + synthesize_leave_event (current_window, msg, GDK_NOTIFY_NONLINEAR); + intermediate = gdk_window_get_parent (current_window); + if (intermediate != common_ancestor) + { + synthesize_leave_events (intermediate, common_ancestor, + msg, GDK_NOTIFY_NONLINEAR_VIRTUAL); + } + intermediate = gdk_window_get_parent (window); + if (intermediate != common_ancestor) + { + synthesize_enter_events (common_ancestor, intermediate, + msg, GDK_NOTIFY_NONLINEAR_VIRTUAL); + } + synthesize_enter_event (window, msg, GDK_NOTIFY_NONLINEAR); + } + } + else + { + /* Dunno where we are coming from */ + synthesize_enter_event (window, msg, GDK_NOTIFY_UNKNOWN); + } + + if (current_window) + gdk_window_unref (current_window); + current_window = window; + gdk_window_ref (current_window); +} + +#endif + static void translate_mouse_coords (GdkWindow *window1, GdkWindow *window2, @@ -1436,7 +1641,11 @@ gdk_event_translate (GdkEvent *event, orig_window = window; event->any.window = window; - event->any.send_event = FALSE; + + /* InSendMessage() does not really mean the same as X11's send_event flag, + * but it is close enough, says jpe@archaeopteryx.com. + */ + event->any.send_event = InSendMessage (); if (window == NULL) { -- 2.30.2